﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json.Linq;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

namespace OTPlus.Core.Content
{
    public class Activity
    {
        
        public static Activity Retrieve(JObject jo)
        { return parseJsonObject(jo); }


        public Actor Actor { get; set; }
        public String ID { get; set; }
        public DateTime Published { get; set; }
        public DateTime Updated { get; set; }
        public DateTime Created { get; set; }
        public String Title { get; set; }
        public String TitleShort { get; set; }
        public String LocationName { get; set; }
        public String LocationAddress { get; set; }
        public Microsoft.SqlServer.Types.SqlGeography Location { get; set; }
        public Int32 Replies { get; set; }

        public List<Content.Comment> Comments { get; set; }

        public static List<Activity> RetrieveSearchThreadsViaToken(string access_token, string search_string)
        {
            List<Activity> results = new List<Activity>();
            results = Retrieve(access_token, "", search_string);

            return results;
        }

        /// <summary>
        /// Returns, from the google api directly, all of the activities for the batch of known users.
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public static List<Activity> RetrieveAllThreadsViaToken(String access_token)
        {
            List<String> userids = new List<string>();
            userids.Add("101888021664339151509");
            userids.Add("114890831955562032598");
            userids.Add("103551294686462547168");
            userids.Add("103913987674263347871");
            userids.Add("107466907386790104735");

            List<Activity> results = new List<Activity>();

            foreach (String s in userids)
            {
                results.AddRange(Retrieve(access_token, s));
            }

            results.Sort((a, b) => DateTime.Compare(b.Published, a.Published));

            return results;
        }


        /// <summary>
        /// Retrieves a list of activities created by a given userid.
        /// </summary>
        /// <param name="access_token">Required.</param>
        /// <param name="userid">???</param>
        /// <param name="search_string">Optional.</param>
        /// <returns></returns>
        public static List<Activity> Retrieve(String access_token, String userid="", string search_string = "")
        {
            string url = string.Empty;
            string apikey = System.Configuration.ConfigurationManager.AppSettings["gplusapikey"];

            if (userid.Length > 0 && search_string.Length < 1)
            {
                url = "https://www.googleapis.com/plus/v1/people/" + userid + "/activities/public?access_token=" + access_token + "&alt=json&fields=items(actor%2Caddress%2Cgeocode%2Cid%2Ckind%2Cobject%2Freplies%2CplaceId%2CplaceName%2Cplaceholder%2Cpublished%2Ctitle%2Cupdated%2Curl%2Cverb)&pp=1&key=" + apikey;
            }

            if (userid.Length < 1 && search_string.Length > 0)
            {
                url = "https://www.googleapis.com/plus/v1/activities?query=" + search_string + "&maxResults=20&orderBy=best&pp=1&key=" + apikey;
            }

            string json_g = String.Empty;
            List<Core.Content.Activity> list = new List<Core.Content.Activity>();


            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                json_g = reader.ReadToEnd();
            }

            JObject o = JObject.Parse(json_g);
            JArray items = (JArray)o["items"];
            String geocode = String.Empty;

            for (int i = 0; i < items.Count; i++)
            {
                JObject item = (JObject)items[i];
                list.Add(Core.Content.Activity.Retrieve(item));
            }

            return list;
        
        }

        /// <summary>
        /// Used primarily for displaying comments for a thread view.
        /// </summary>
        /// <param name="argument"></param>
        /// <returns></returns>
        public static DataTransfer.ActivityResponse RetrieveComments(DataTransfer.ActivitySelect argument)
        {
            string apikey = System.Configuration.ConfigurationManager.AppSettings["gplusapikey"];
            String url = "https://www.googleapis.com/plus/v1/activities/" + argument.ActivityID
                + "/comments?access_token=" + argument.AccessToken
                + "&alt=json&pp=1&key=" + apikey
                + "&maxResults=" + argument.PaginationRequest.ItemsPerPage
                + "&pageToken=" + argument.PaginationRequest.PaginationToken;
            string json_g = String.Empty;
            DataTransfer.ActivityResponse result = new DataTransfer.ActivityResponse();
            
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                json_g = reader.ReadToEnd();
            }
           

            JObject o = JObject.Parse(json_g);

            //Got the data above into "o".

            result.Activity = retrieveActivityHeader(argument.AccessToken, argument.ActivityID);
            result.Activity.Comments = new List<Comment>();

            //in order to make the thread look normal, we take the first activity (retrieved from retrieveActivityHeader),
            //then we make a new comment and insert it. this makes viewing the "thread" possible.

            Comment topComment = new Comment();
            topComment.ActivityID = result.Activity.ID;
            topComment.Actor = result.Activity.Actor;
            topComment.Content = result.Activity.Title;
            topComment.Published = result.Activity.Published;

            result.Activity.TitleShort = result.Activity.TitleShort;
            result.Activity.Replies = result.Activity.Replies;

            //iterate through the items, building a list of comments

            JArray items = (JArray)o["items"];

            for (int i = 0; i < items.Count; i++)
            {
                JObject item = (JObject)items[i];
                Content.Comment comment = new Comment();

                JArray inReplyTo = (JArray)item["inReplyTo"];
                JObject commentObject = (JObject)item["object"];
                JObject actor = (JObject)item["actor"];
                 

                comment.ActivityID = inReplyTo[0]["id"].ToString();
                comment.ActivityURL = inReplyTo[0]["url"].ToString();
                
                comment.Actor = new Actor();
                comment.Actor.ID = actor["id"].ToString();
                comment.Actor.Image = actor["image"]["url"].ToString();
                comment.Actor.Name = actor["displayName"].ToString();
                comment.Actor.Url = actor["url"].ToString();

                comment.Content = commentObject["content"].ToString();
                comment.Content = buildCommentBody(comment.Content);
                comment.ID = item["id"].ToString();
                comment.ObjectType = commentObject["objectType"].ToString();
                comment.Published = DateTime.Parse(item["published"].ToString());
                comment.SelfLink = item["selfLink"].ToString();
                comment.Updated = DateTime.Parse(item["updated"].ToString());
                comment.Verb = String.Empty;

                result.Activity.Comments.Add(comment);
            }

            //add the manually created comment in, maybe
            if (argument.IncludeActivityCommentInFulfillment)
            { result.Activity.Comments.Add(topComment); }
            

            //sort the whole mess
            result.Activity.Comments.Sort((a, b) => DateTime.Compare(a.Published, b.Published));

            return result;

        }

        private static String buildCommentBody(String content)
        {
            Int32 tagStart = 0;

            tagStart = content.IndexOf("http://i.imgur.com/");
            if (tagStart > 1)
                content = EmbedImgur.Embed(content);

            tagStart = content.IndexOf("http://www.youtube.com/");
            if (tagStart > 1)
                content = EmbedYoutube.Embed(content);
            

            return content;
        }
        
        private static Activity parseJsonObject(JObject jo)
        {
            DateTime when;
            Activity result = new Activity();
            String geocode = String.Empty;

            result.Actor = new Actor();

 
 //           lat = Double.Parse(geocode.Substring(0, geocode.IndexOf(" ")));
  //          lon = Double.Parse(geocode.Substring(geocode.IndexOf(" ")));

            //Proximity.Location point = new Proximity.Location(lat, lon);

            when = DateTime.Parse(jo["published"].ToString());
            var actor = jo["actor"];
            var image = actor["image"];

            var itemobject = jo["object"];
            var replies = itemobject["replies"];
            var totalitems = replies["totalItems"].ToString();

            result.ID = jo["id"].ToString();
            result.Actor.ID = actor["id"].ToString();
            result.Actor.Image = image["url"].ToString();
            result.Actor.Name = actor["displayName"].ToString();
            result.Actor.Url = actor["url"].ToString();
            result.Location = Microsoft.SqlServer.Types.SqlGeography.Point(32, 32, 4326);// Geo.BuildGeography(point);
            result.Published = DateTime.Parse(jo["published"].ToString());
            result.Title = jo["title"].ToString().Replace("'", "|@|"); //switching out single ticks to |@|
            result.TitleShort = jo["title"].ToString().Replace("'", "|@|");
            result.Updated = DateTime.Parse(jo["updated"].ToString());
            result.Replies = Int32.Parse(totalitems);
            //result.LocationAddress = jo["address"].ToString();

            if (jo["placeName"] != null)
            { result.LocationName = jo["placeName"].ToString(); }
            else
            { result.LocationName = String.Empty; }

            return result;
        }

        private static Activity retrieveActivityHeader(String access_token, String activityID)
        {
            string apikey = System.Configuration.ConfigurationManager.AppSettings["gplusapikey"];
            String url = "https://www.googleapis.com/plus/v1/activities/"+ activityID +"?access_token="+access_token+"&alt=json&pp=1&key=" + apikey;
            string json_g = String.Empty;
            Activity result = new Activity();

            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                json_g = reader.ReadToEnd();
            }

            JObject o = JObject.Parse(json_g);

            //get the images out
            result.Title = extractImage(o) + "<br /><br />" + o["object"]["content"].ToString();

            result.TitleShort = o["title"].ToString();
            result.Published = DateTime.Parse(o["published"].ToString());
            result.ID = o["id"].ToString();
            result.Replies = Int32.Parse(o["object"]["replies"]["totalItems"].ToString());
            
            result.Actor = new Actor();
            result.Actor.ID = o["actor"]["id"].ToString();
            result.Actor.Image = o["actor"]["image"]["url"].ToString();
            result.Actor.Name = o["actor"]["displayName"].ToString();
            result.Actor.Url = o["actor"]["url"].ToString();

            return result;


        }

        private static String extractImage(JObject jo)
        {
            String s;

            if (jo != null &&
                jo["object"] != null &&
                jo["object"]["attachments"] != null &&
                jo["object"]["attachments"][0] != null &&
                jo["object"]["attachments"][0]["image"] != null &&
                jo["object"]["attachments"][0]["image"]["url"] != null)
            {
                s = @"<img src=""" + jo["object"]["attachments"][0]["image"]["url"].ToString() + @"""/>";
            }
            else
            {
                s = String.Empty;
            }

            return s;            
        }
    }
}